home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / gui / x / xfig.lha / src / x11 / e_movept.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  18.9 KB  |  771 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  *
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. #include "fig.h"
  14. #include "resources.h"
  15. #include "mode.h"
  16. #include "object.h"
  17. #include "paintop.h"
  18. #include "u_draw.h"
  19. #include "u_search.h"
  20. #include "u_create.h"
  21. #include "u_elastic.h"
  22. #include "u_list.h"
  23. #include "u_undo.h"
  24. #include "w_canvas.h"
  25. #include "w_mousefun.h"
  26.  
  27. extern void     force_anglegeom(), force_noanglegeom();
  28.  
  29. /* local routine declarations */
  30.  
  31. static F_point *moved_point;
  32.  
  33. static Boolean    init_ellipsepointmoving();
  34. static int    init_arcpointmoving();
  35. static int    init_linepointmoving();
  36. static int    init_splinepointmoving();
  37. static int    init_compoundpointmoving();
  38.  
  39. static int    relocate_arcpoint();
  40. static int    relocate_ellipsepoint();
  41. static int    relocate_linepoint();
  42. static int    relocate_splinepoint();
  43. static int    assign_newboxpoint();
  44.  
  45. static int    init_move_point();
  46. static int    init_arb_move_point();
  47. static int    init_stretch_move_point();
  48.  
  49. static int    fix_movedarcpoint();
  50. static int    fix_movedellipsepoint();
  51. static int    fix_movedsplinepoint();
  52. static int    fix_box();
  53. static int    fix_movedlinepoint();
  54. static int    fix_movedlatexlinepoint();
  55.  
  56. static int    cancel_movedarcpoint();
  57. static int    cancel_movedellipsepoint();
  58. static int    cancel_movedsplinepoint();
  59. static int    cancel_box();
  60. static int    cancel_movedlinepoint();
  61.  
  62. move_point_selected()
  63. {
  64.     set_mousefun("move point", "horiz/vert move", "");
  65.     canvas_kbd_proc = null_proc;
  66.     canvas_locmove_proc = null_proc;
  67.     init_searchproc_left(init_arb_move_point);
  68.     init_searchproc_middle(init_stretch_move_point);
  69.     canvas_leftbut_proc = point_search_left;
  70.     canvas_middlebut_proc = point_search_middle;
  71.     canvas_rightbut_proc = null_proc;
  72.     set_cursor(pick9_cursor);
  73.     force_anglegeom();
  74. }
  75.  
  76. static
  77. init_arb_move_point(obj, type, x, y, p, q)
  78.     char       *obj;
  79.     int            type, x, y;
  80.     F_point       *p, *q;
  81. {
  82.     constrained = MOVE_ARB;
  83.     init_move_point(obj, type, x, y, p, q);
  84.     set_mousefun("new posn", "", "cancel");
  85.     draw_mousefun_canvas();
  86.     canvas_middlebut_proc = null_proc;
  87. }
  88.  
  89. static
  90. init_stretch_move_point(obj, type, x, y, p, q)
  91.     char       *obj;
  92.     int            type, x, y;
  93.     F_point       *p, *q;
  94. {
  95.     constrained = MOVE_HORIZ_VERT;
  96.     init_move_point(obj, type, x, y, p, q);
  97.     set_mousefun("", "new posn", "cancel");
  98.     draw_mousefun_canvas();
  99.     canvas_middlebut_proc = canvas_leftbut_proc;
  100.     canvas_leftbut_proc = null_proc;
  101. }
  102.  
  103. static
  104. init_move_point(obj, type, x, y, p, q)
  105.     char       *obj;
  106.     int            type, x, y;
  107.     F_point       *p, *q;
  108. {
  109.     left_point = p;
  110.     moved_point = q;
  111.     switch (type) {
  112.     case O_POLYLINE:
  113.     cur_l = (F_line *) obj;
  114.     right_point = q->next;
  115.     init_linepointmoving();
  116.     break;
  117.     case O_SPLINE:
  118.     cur_s = (F_spline *) obj;
  119.     right_point = q->next;
  120.     init_splinepointmoving();
  121.     break;
  122.     case O_ELLIPSE:
  123.     force_noanglegeom();
  124.     /* dirty trick - arcpoint_num is stored in p */
  125.     movedpoint_num = (int) p;
  126.     cur_e = (F_ellipse *) obj;
  127.     if (!init_ellipsepointmoving()) /* selected center, ignore */
  128.         return;
  129.     break;
  130.     case O_ARC:
  131.     force_noanglegeom();
  132.     /* dirty trick - arcpoint_num is stored in p */
  133.     movedpoint_num = (int) p;
  134.     cur_a = (F_arc *) obj;
  135.     init_arcpointmoving();
  136.     break;
  137.     case O_COMPOUND:
  138.     force_noanglegeom();
  139.     /* dirty trick - posn of corner is stored in p and q */
  140.     cur_x = (int) p;
  141.     cur_y = (int) q;
  142.     cur_c = (F_compound *) obj;
  143.     init_compoundpointmoving();
  144.     break;
  145.     default:
  146.     return;
  147.     }
  148. }
  149.  
  150. static
  151. wrapup_movepoint()
  152. {
  153.     reset_action_on();
  154.     move_point_selected();
  155.     draw_mousefun_canvas();
  156. }
  157.  
  158. /*************************  ellipse  *******************************/
  159.  
  160. static        Boolean
  161. init_ellipsepointmoving()
  162. {
  163.     double        dx, dy, l;
  164.  
  165.     if (constrained &&
  166.     (cur_e->type == T_CIRCLE_BY_DIA || cur_e->type == T_CIRCLE_BY_RAD)) {
  167.     put_msg("Constrained move not supported for CIRCLES");
  168.     return False;        /* abort - constrained move for circle not
  169.                  * needed */
  170.     }
  171.     if (movedpoint_num == 0) {
  172.     if (cur_e->type == T_ELLIPSE_BY_RAD ||
  173.         cur_e->type == T_CIRCLE_BY_RAD) {
  174.         put_msg("Cannot move CENTER point");
  175.         return False;    /* abort - center point is selected */
  176.     }
  177.     cur_x = cur_e->start.x;
  178.     cur_y = cur_e->start.y;
  179.     fix_x = cur_e->end.x;
  180.     fix_y = cur_e->end.y;
  181.     } else {
  182.     cur_x = cur_e->end.x;
  183.     cur_y = cur_e->end.y;
  184.     fix_x = cur_e->start.x;
  185.     fix_y = cur_e->start.y;
  186.     }
  187.     if (constrained) {
  188.     dx = cur_x - fix_x;
  189.     dy = cur_y - fix_y;
  190.     l = sqrt(dx * dx + dy * dy);
  191.     cosa = fabs(dx / l);
  192.     sina = fabs(dy / l);
  193.     }
  194.     cur_angle = cur_e->angle;
  195.     set_action_on();
  196.     toggle_ellipsemarker(cur_e);
  197.     draw_ellipse(cur_e, ERASE);
  198.     switch (cur_e->type) {
  199.     case T_ELLIPSE_BY_RAD:
  200.     canvas_locmove_proc = constrained_resizing_ebr;
  201.     elastic_ebr();
  202.     break;
  203.     case T_CIRCLE_BY_RAD:
  204.     canvas_locmove_proc = resizing_cbr;
  205.     elastic_cbr();
  206.     break;
  207.     case T_ELLIPSE_BY_DIA:
  208.     canvas_locmove_proc = constrained_resizing_ebd;
  209.     elastic_ebd();
  210.     break;
  211.     case T_CIRCLE_BY_DIA:
  212.     canvas_locmove_proc = resizing_cbd;
  213.     elastic_cbd();
  214.     break;
  215.     }
  216.     from_x = cur_x;
  217.     from_y = cur_y;
  218.     set_temp_cursor(crosshair_cursor);
  219.     canvas_leftbut_proc = fix_movedellipsepoint;
  220.     canvas_rightbut_proc = cancel_movedellipsepoint;
  221.     return True;        /* all is Ok */
  222. }
  223.  
  224. static
  225. cancel_movedellipsepoint()
  226. {
  227.     switch (cur_e->type) {
  228.     case T_ELLIPSE_BY_RAD:
  229.     elastic_ebr();
  230.     break;
  231.     case T_CIRCLE_BY_RAD:
  232.     elastic_cbr();
  233.     break;
  234.     case T_ELLIPSE_BY_DIA:
  235.     elastic_ebd();
  236.     break;
  237.     case T_CIRCLE_BY_DIA:
  238.     elastic_cbd();
  239.     break;
  240.     }
  241.     draw_ellipse(cur_e, PAINT);
  242.     toggle_ellipsemarker(cur_e);
  243.     wrapup_movepoint();
  244. }
  245.  
  246. static
  247. fix_movedellipsepoint(x, y)
  248.     int            x, y;
  249. {
  250.     switch (cur_e->type) {
  251.     case T_ELLIPSE_BY_RAD:
  252.     elastic_ebr();
  253.     break;
  254.     case T_CIRCLE_BY_RAD:
  255.     elastic_cbr();
  256.     break;
  257.     case T_ELLIPSE_BY_DIA:
  258.     elastic_ebd();
  259.     break;
  260.     case T_CIRCLE_BY_DIA:
  261.     elastic_cbd();
  262.     break;
  263.     }
  264.     adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  265.     new_e = copy_ellipse(cur_e);
  266.     relocate_ellipsepoint(new_e, cur_x, cur_y, movedpoint_num);
  267.     change_ellipse(cur_e, new_e);
  268.     toggle_ellipsemarker(new_e);
  269.     wrapup_movepoint();
  270. }
  271.  
  272. static
  273. relocate_ellipsepoint(ellipse, x, y, point_num)
  274.     F_ellipse       *ellipse;
  275.     int            x, y, point_num;
  276. {
  277.     int            dx, dy;
  278.  
  279.     set_temp_cursor(wait_cursor);
  280.     draw_ellipse(ellipse, ERASE);
  281.     if (point_num == 0) {    /* starting point is selected  */
  282.     fix_x = ellipse->end.x;
  283.     fix_y = ellipse->end.y;
  284.     ellipse->start.x = x;
  285.     ellipse->start.y = y;
  286.     } else {
  287.     fix_x = ellipse->start.x;
  288.     fix_y = ellipse->start.y;
  289.     ellipse->end.x = x;
  290.     ellipse->end.y = y;
  291.     }
  292.     cur_angle = ellipse->angle;
  293.     switch (ellipse->type) {
  294.     case T_ELLIPSE_BY_RAD:
  295.     ellipse->radiuses.x = abs(x - fix_x);
  296.     ellipse->radiuses.y = abs(y - fix_y);
  297.     break;
  298.     case T_CIRCLE_BY_RAD:
  299.     dx = fix_x - x;
  300.     dy = fix_y - y;
  301.     ellipse->radiuses.x = sqrt((double) (dx * dx + dy * dy)) + .5;
  302.     ellipse->radiuses.y = ellipse->radiuses.x;
  303.     break;
  304.     case T_ELLIPSE_BY_DIA:
  305.     ellipse->center.x = (fix_x + x) / 2;
  306.     ellipse->center.y = (fix_y + y) / 2;
  307.     ellipse->radiuses.x = abs(ellipse->center.x - fix_x);
  308.     ellipse->radiuses.y = abs(ellipse->center.y - fix_y);
  309.     break;
  310.     case T_CIRCLE_BY_DIA:
  311.     dx = ellipse->center.x = (fix_x + x) / 2 + .5;
  312.     dy = ellipse->center.y = (fix_y + y) / 2 + .5;
  313.     dx -= x;
  314.     dy -= y;
  315.     ellipse->radiuses.x = sqrt((double) (dx * dx + dy * dy)) + .5;
  316.     ellipse->radiuses.y = ellipse->radiuses.x;
  317.     break;
  318.     }
  319.     /* if this WAS an ellipse and is NOW a circle (radii are equal), change type */
  320.     if (ellipse->type == T_ELLIPSE_BY_RAD || ellipse->type == T_ELLIPSE_BY_DIA) {
  321.     if (ellipse->radiuses.x == ellipse->radiuses.y)
  322.         ellipse->type += 2;
  323.     }
  324.     draw_ellipse(ellipse, PAINT);
  325.     reset_cursor();
  326. }
  327.  
  328. /***************************  arc  *********************************/
  329.  
  330. static
  331. init_arcpointmoving()
  332. {
  333.     set_action_on();
  334.     toggle_arcmarker(cur_a);
  335.     cur_x = cur_a->point[movedpoint_num].x;
  336.     cur_y = cur_a->point[movedpoint_num].y;
  337.     set_temp_cursor(crosshair_cursor);
  338.     win_setmouseposition(canvas_win, cur_x, cur_y);
  339.     elastic_arclink();
  340.     canvas_locmove_proc = reshaping_arc;
  341.     canvas_leftbut_proc = fix_movedarcpoint;
  342.     canvas_rightbut_proc = cancel_movedarcpoint;
  343. }
  344.  
  345. static
  346. cancel_movedarcpoint()
  347. {
  348.     elastic_arclink();
  349.     toggle_arcmarker(cur_a);
  350.     wrapup_movepoint();
  351. }
  352.  
  353. static
  354. fix_movedarcpoint(x, y)
  355.     int            x, y;
  356. {
  357.     elastic_arclink();
  358.     adjust_pos(x, y, cur_a->point[movedpoint_num].x,
  359.            cur_a->point[movedpoint_num].y, &x, &y);
  360.     new_a = copy_arc(cur_a);
  361.     relocate_arcpoint(new_a, x, y, movedpoint_num);
  362.     change_arc(cur_a, new_a);
  363.     toggle_arcmarker(new_a);
  364.     wrapup_movepoint();
  365. }
  366.  
  367. static
  368. relocate_arcpoint(arc, x, y, movedpoint_num)
  369.     F_arc       *arc;
  370.     int            x, y, movedpoint_num;
  371. {
  372.     float        xx, yy;
  373.     F_pos        p[3];
  374.  
  375.     p[0] = arc->point[0];
  376.     p[1] = arc->point[1];
  377.     p[2] = arc->point[2];
  378.     p[movedpoint_num].x = x;
  379.     p[movedpoint_num].y = y;
  380.     if (compute_arccenter(p[0], p[1], p[2], &xx, &yy)) {
  381.     set_temp_cursor(wait_cursor);
  382.     draw_arc(arc, ERASE);    /* erase old arc */
  383.     arc->point[movedpoint_num].x = x;
  384.     arc->point[movedpoint_num].y = y;
  385.     arc->center.x = xx;
  386.     arc->center.y = yy;
  387.     arc->direction = compute_direction(p[0], p[1], p[2]);
  388.     draw_arc(arc, PAINT);    /* draw new arc */
  389.     reset_cursor();
  390.     }
  391. }
  392.  
  393. /**************************  spline  *******************************/
  394.  
  395. static
  396. init_splinepointmoving()
  397. {
  398.     F_point       *p;
  399.  
  400.     set_action_on();
  401.     toggle_splinemarker(cur_s);
  402.     from_x = cur_x = moved_point->x;
  403.     from_y = cur_y = moved_point->y;
  404.     set_temp_cursor(crosshair_cursor);
  405.     if (open_spline(cur_s)) {
  406.     if (left_point == NULL || right_point == NULL) {
  407.             if (left_point != NULL) {
  408.                 fix_x = left_point->x;
  409.                 fix_y = left_point->y;
  410.             } else if (right_point != NULL) {
  411.                 fix_x = right_point->x;
  412.                 fix_y = right_point->y;
  413.             }
  414.         if (latexline_mode || latexarrow_mode) {
  415.                 canvas_locmove_proc = latex_line;
  416.                 cur_latexcursor = crosshair_cursor;
  417.             } else if (mountain_mode || manhattan_mode) {
  418.                 canvas_locmove_proc = constrainedangle_line;
  419.             } else {
  420.                 /* freehand line */
  421.                 canvas_locmove_proc = reshaping_line;
  422.             }
  423.     } else {
  424.             /* linelink, always freehand */
  425.         force_noanglegeom();
  426.         canvas_locmove_proc = reshaping_line;
  427.     }
  428.     } else {
  429.     /* must be closed spline */
  430.     force_noanglegeom();
  431.     canvas_locmove_proc = reshaping_line;
  432.     if (left_point == NULL) {
  433.         for (left_point = right_point, p = left_point->next;
  434.          p->next != NULL;
  435.          left_point = p, p = p->next);
  436.     }
  437.     }
  438.     elastic_linelink();
  439.     canvas_leftbut_proc = fix_movedsplinepoint;
  440.     canvas_rightbut_proc = cancel_movedsplinepoint;
  441. }
  442.  
  443. static
  444. cancel_movedsplinepoint()
  445. {
  446.     elastic_linelink();
  447.     toggle_splinemarker(cur_s);
  448.     wrapup_movepoint();
  449. }
  450.  
  451. static
  452. fix_movedsplinepoint(x, y)
  453.     int            x, y;
  454. {
  455.     (*canvas_locmove_proc) (x, y);
  456.     elastic_linelink();
  457.     old_s = copy_spline(cur_s);
  458.     clean_up();
  459.     set_latestspline(old_s);
  460.     set_action_object(F_CHANGE, O_SPLINE);
  461.     old_s->next = cur_s;
  462.     relocate_splinepoint(cur_s, cur_x, cur_y, moved_point);
  463.     toggle_splinemarker(cur_s);
  464.     wrapup_movepoint();
  465. }
  466.  
  467. static
  468. relocate_splinepoint(s, x, y, moved_point)
  469.     F_spline       *s;
  470.     int            x, y;
  471.     F_point       *moved_point;
  472. {
  473.     set_temp_cursor(wait_cursor);
  474.     draw_spline(s, ERASE);    /* erase old spline */
  475.     moved_point->x = x;
  476.     moved_point->y = y;
  477.     if (closed_spline(s)) {
  478.     left_point->next->x = x;
  479.     left_point->next->y = y;
  480.     }
  481.     if (int_spline(s))
  482.     remake_control_points(s);
  483.     draw_spline(s, PAINT);    /* draw spline with moved point */
  484.     set_modifiedflag();
  485.     reset_cursor();
  486. }
  487.  
  488. /***************************  compound    ********************************/
  489.  
  490. static        prescale_compound(), cancel_compound();
  491.  
  492. static
  493. init_compoundpointmoving()
  494. {
  495.     double        dx, dy, l;
  496.  
  497.     set_action_on();
  498.     if (cur_x == cur_c->nwcorner.x)
  499.     fix_x = cur_c->secorner.x;
  500.     else
  501.     fix_x = cur_c->nwcorner.x;
  502.     if (cur_y == cur_c->nwcorner.y)
  503.     fix_y = cur_c->secorner.y;
  504.     else
  505.     fix_y = cur_c->nwcorner.y;
  506.     from_x = cur_x;
  507.     from_y = cur_y;
  508.     toggle_compoundmarker(cur_c);
  509.     draw_compoundelements(cur_c, ERASE);
  510.     set_temp_cursor(crosshair_cursor);
  511.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  512.     if (constrained) {
  513.     dx = cur_x - fix_x;
  514.     dy = cur_y - fix_y;
  515.     l = sqrt(dx * dx + dy * dy);
  516.     cosa = fabs(dx / l);
  517.     sina = fabs(dy / l);
  518.     }
  519.     canvas_locmove_proc = constrained_resizing_box;
  520.     canvas_leftbut_proc = prescale_compound;
  521.     canvas_rightbut_proc = cancel_compound;
  522. }
  523.  
  524. static
  525. cancel_compound()
  526. {
  527.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  528.     draw_compoundelements(cur_c, PAINT);
  529.     toggle_compoundmarker(cur_c);
  530.     wrapup_movepoint();
  531. }
  532.  
  533. extern        scale_compound();
  534.  
  535. static
  536. prescale_compound(x, y)
  537.     int            x, y;
  538. {
  539.     float        scalex, scaley;
  540.  
  541.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  542.     adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
  543.  
  544.     scalex = ((float) (cur_x - fix_x)) / (from_x - fix_x);
  545.     scaley = ((float) (cur_y - fix_y)) / (from_y - fix_y);
  546.     scale_compound(cur_c, scalex, scaley, fix_x, fix_y);
  547.  
  548.     draw_compoundelements(cur_c, PAINT);
  549.     set_lastposition(from_x, from_y);
  550.     set_newposition(cur_x, cur_y);
  551.     clean_up();
  552.     set_action_object(F_SCALE, O_COMPOUND);
  553.     set_latestcompound(cur_c);
  554.     toggle_compoundmarker(cur_c);
  555.     set_modifiedflag();
  556.     reset_cursor();
  557.     wrapup_movepoint();
  558. }
  559.  
  560. /***************************  line  ********************************/
  561.  
  562. static
  563. init_linepointmoving()
  564. {
  565.     F_point       *p;
  566.  
  567.     set_action_on();
  568.     toggle_linemarker(cur_l);
  569.     from_x = cur_x = moved_point->x;
  570.     from_y = cur_y = moved_point->y;
  571.     set_temp_cursor(crosshair_cursor);
  572.     switch (cur_l->type) {
  573.     case T_POLYGON:
  574.     if (left_point == NULL)
  575.         for (left_point = right_point, p = left_point->next;
  576.          p->next != NULL;
  577.          left_point = p, p = p->next);
  578.         force_noanglegeom();
  579.     canvas_locmove_proc = reshaping_line;
  580.     break;
  581.  
  582.     case T_BOX:
  583.     case T_ARC_BOX:
  584.     case T_EPS_BOX:
  585.     if (right_point->next == NULL) {    /* point 4 */
  586.         fix_x = cur_l->points->next->x;
  587.         fix_y = cur_l->points->next->y;
  588.     } else {
  589.         fix_x = right_point->next->x;
  590.         fix_y = right_point->next->y;
  591.     }
  592.     draw_line(cur_l, ERASE);
  593.  
  594.     if (constrained) {
  595.         double        dx, dy, l;
  596.  
  597.         dx = cur_x - fix_x;
  598.         dy = cur_y - fix_y;
  599.         l = sqrt(dx * dx + dy * dy);
  600.         cosa = fabs(dx / l);
  601.         sina = fabs(dy / l);
  602.     }
  603.  
  604.         force_noanglegeom();
  605.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  606.     canvas_locmove_proc = constrained_resizing_box;
  607.     canvas_leftbut_proc = fix_box;
  608.     canvas_rightbut_proc = cancel_box;
  609.     return;
  610.  
  611.     case T_POLYLINE:
  612.     if (left_point != NULL) {
  613.         if (left_point == cur_l->points) {
  614.         if (cur_l->back_arrow)    /* backward arrow  */
  615.             draw_arrow(cur_x, cur_y,
  616.                    left_point->x, left_point->y,
  617.                    cur_l->back_arrow, ERASE,
  618.                    cur_l->color);
  619.         }
  620.     } else if (cur_l->back_arrow)    /* backward arrow  */
  621.         draw_arrow(right_point->x, right_point->y,
  622.                cur_x, cur_y, cur_l->back_arrow, ERASE,
  623.                cur_l->color);
  624.     if (right_point != NULL) {
  625.         if (cur_l->for_arrow && right_point->next == NULL)
  626.         draw_arrow(cur_x, cur_y, right_point->x, right_point->y,
  627.                cur_l->for_arrow, ERASE,
  628.                cur_l->color);
  629.     } else if (cur_l->for_arrow)    /* f arrow */
  630.         draw_arrow(left_point->x, left_point->y,
  631.                cur_x, cur_y, cur_l->for_arrow, ERASE,
  632.                cur_l->color);
  633.     if (left_point == NULL || right_point == NULL) {
  634.         if (left_point != NULL) {
  635.         fix_x = left_point->x;
  636.         fix_y = left_point->y;
  637.         } else if (right_point != NULL) {
  638.         fix_x = right_point->x;
  639.         fix_y = right_point->y;
  640.         }
  641.             if (latexline_mode || latexarrow_mode) {
  642.                 canvas_locmove_proc = latex_line;
  643.         cur_latexcursor = crosshair_cursor;
  644.             } else if (mountain_mode || manhattan_mode) {
  645.                 canvas_locmove_proc = constrainedangle_line;
  646.             } else {
  647.         /* freehand line */
  648.         canvas_locmove_proc = reshaping_line;
  649.         }
  650.     } else {
  651.         /* linelink, always freehand */
  652.             force_noanglegeom();
  653.         canvas_locmove_proc = reshaping_line;
  654.     }
  655.     break;
  656.     }
  657.     elastic_linelink();
  658.     canvas_leftbut_proc = fix_movedlinepoint;
  659.     canvas_rightbut_proc = cancel_movedlinepoint;
  660. }
  661.  
  662. static
  663. cancel_box()
  664. {
  665.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  666.     draw_line(cur_l, PAINT);
  667.     toggle_linemarker(cur_l);
  668.     wrapup_movepoint();
  669. }
  670.  
  671. static
  672. fix_box(x, y)
  673.     int            x, y;
  674. {
  675.     elastic_box(fix_x, fix_y, cur_x, cur_y);
  676.     adjust_box_pos(x, y, from_x, from_y, &x, &y);
  677.     new_l = copy_line(cur_l);
  678.     draw_line(cur_l, ERASE);
  679.     if (new_l->type == T_EPS_BOX) {
  680.     if (signof(fix_x - from_x) != signof(fix_x - x))
  681.         new_l->eps->flipped = 1 - new_l->eps->flipped;
  682.     if (signof(fix_y - from_y) != signof(fix_y - y))
  683.         new_l->eps->flipped = 1 - new_l->eps->flipped;
  684.     }
  685.     assign_newboxpoint(new_l, fix_x, fix_y, x, y);
  686.     change_line(cur_l, new_l);
  687.     draw_line(new_l, PAINT);
  688.     toggle_linemarker(new_l);
  689.     wrapup_movepoint();
  690. }
  691.  
  692. static
  693. assign_newboxpoint(b, x1, y1, x2, y2)
  694.     F_line       *b;
  695.     int            x1, y1, x2, y2;
  696. {
  697.     F_point       *p;
  698.  
  699.     p = b->points;
  700.     if (p->x != x1)
  701.     p->x = x2;
  702.     if (p->y != y1)
  703.     p->y = y2;
  704.     p = p->next;
  705.     if (p->x != x1)
  706.     p->x = x2;
  707.     if (p->y != y1)
  708.     p->y = y2;
  709.     p = p->next;
  710.     if (p->x != x1)
  711.     p->x = x2;
  712.     if (p->y != y1)
  713.     p->y = y2;
  714.     p = p->next;
  715.     if (p->x != x1)
  716.     p->x = x2;
  717.     if (p->y != y1)
  718.     p->y = y2;
  719.     p = p->next;
  720.     if (p->x != x1)
  721.     p->x = x2;
  722.     if (p->y != y1)
  723.     p->y = y2;
  724. }
  725.  
  726. static
  727. cancel_movedlinepoint()
  728. {
  729.     elastic_linelink();
  730.     toggle_linemarker(cur_l);
  731.     wrapup_movepoint();
  732. }
  733.  
  734. static
  735. fix_movedlinepoint(x, y)
  736.     int            x, y;
  737. {
  738.     (*canvas_locmove_proc) (x, y);
  739.     elastic_linelink();
  740.     if (cur_latexcursor != crosshair_cursor)
  741.     set_temp_cursor(crosshair_cursor);
  742.     /* make a copy of the original and save as unchanged object */
  743.     old_l = copy_line(cur_l);
  744.     clean_up();
  745.     set_latestline(old_l);
  746.     set_action_object(F_CHANGE, O_POLYLINE);
  747.     old_l->next = cur_l;
  748.     /* now change the original to become the new object */
  749.     relocate_linepoint(cur_l, cur_x, cur_y, moved_point, left_point);
  750.     toggle_linemarker(cur_l);
  751.     wrapup_movepoint();
  752. }
  753.  
  754. static
  755. relocate_linepoint(line, x, y, moved_point, left_point)
  756.     F_line       *line;
  757.     int            x, y;
  758.     F_point       *moved_point, *left_point;
  759. {
  760.     draw_line(line, ERASE);
  761.     if (line->type == T_POLYGON)
  762.     if (line->points == moved_point) {
  763.         left_point->next->x = x;
  764.         left_point->next->y = y;
  765.     }
  766.     moved_point->x = x;
  767.     moved_point->y = y;
  768.     set_modifiedflag();
  769.     draw_line(line, PAINT);
  770. }
  771.